require 'gserver'
require 'gmailer'

class MyServer < GServer

  def send_and_log( io, text )
    puts Time.now.to_s + "[send] " + text
    io.puts text
  end

  def unread_for_label( label )

  end

  def serve( io )
    @session_id = Time.now.to_i
    @msg_seq = 1
    @mstore = Array.new
    puts "hola"
    send_and_log(io, "* OK [CAPABILITY IMAP4 IMAP4REV1 AUTH=PLAIN] localhost GMailProxy at #{Time.now.to_s}")
    #loop do
  
    #end
    while ( line = io.gets )
      puts line
      case line
        when /(.*) CAPABILITY/
          send_and_log(io, "* CAPABILITY IMAP4 IMAP4REV1 AUTH=PLAIN")
          send_and_log(io, "#{$1} OK CAPABILITY completed")
        when /(.+) LOGIN "(.+)" "(.+)"/
          @g = GMailer.connect($2, $3)
          send_and_log(io, "#{$1} OK User logged in")
        when /(.+) LIST "" ""/
          send_and_log(io, "* LIST (\\Noselect) \"/\" \"\"")
          send_and_log(io, "#{$1} OK LIST completed")
        when /(.+) LIST "" "(.+)"/
          counter = $1
          name = $2
          tree = name.split('/')
          if ( tree.size == 1 )
            puts "Nothing to list (#{name})"
          else
           if ( tree[(tree.size)-1] != "%" )
            labels = @g.labels
              labels.each do |l|
                send_and_log(io, "* LIST (\\Marked) \"/\" #{l} ")
              end
            else
              puts "Nothing to list (#{name})"
            end
          end
          # LIST "" "label"
          # if we get LIST "" "label/%" , skip this, labels
          # have no subfolders
          send_and_log(io, "#{counter} OK LIST completed")
        when /(.+) STATUS "(.+)" \((.+)\)/
          send_and_log(io, "* STATUS #{$2} (UNSEEN 2)")
          send_and_log(io, "#{$1} OK STATUS completed")
        when /(.+) SELECT "(.+)"/
          @mstore = Array.new
          label = $2
          puts "Client selected label #{label}"
          @selected = label
          counter = 1
          messages = @g.messages(:label=> label)
          unread = 0
          first_unread = nil
          messages.each do |m|
            (unread = unread + 1 ) if m.new?
            (first_unread = counter) if first_unread.nil?
            @mstore[counter] = m
            counter = counter + 1
          end
          puts "#{unread} unread messages in #{label} (#{@mstore.size} total)"

          send_and_log(io, '* FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent)')
          send_and_log(io, '* OK [PERMANENTFLAGS (\* \Draft \Answered \Flagged \Deleted \Seen)] Limited')
          send_and_log(io, "* #{@mstore.size} EXISTS")
          send_and_log(io, "* #{unread} RECENT")
          if not first_unread.nil?
            send_and_log(io, "* OK [UNSEEN #{first_unread}]")
          end
          send_and_log(io, "* OK [UIDVALIDITY #{Time.now.to_i}] Ok")
          send_and_log(io, "* OK [UIDNEXT #{@mstore.size + 1}]")
          #send_and_log(io, "#{$1} OK [READ-WRITE] Completed")
          send_and_log(io, "#{$1} OK Completed")
        when /(.+) UID FETCH (.+) \((.+)\)/
          #puts "peo {#{$1}} {#{$2}} {#{$3}}"
          command_nr = $1
          options_string = $3
          #puts "peo2"
          range = ($2).split(":")
          #puts "peo3 {#{options_string}}"
          request_options = options_string.split(" ")
          #puts "peo4"
          range_from = range[0].to_i
          #puts "peo5"
          #puts "- range from #{range_from}"
          #puts "peo6"
          if range.size == 1
            range_to = range[0].to_i
            #puts "- range to #{range_to}"
          else
            if range[1] == "*"
              range_to = (@mstore.size)
            else
              range_to = range[1].to_i
            end
            #puts "- range to #{range_to}"
          end
          puts "Fetch command in label #{@selected} range #{range_from} t #{range_to} with options #{request_options.join(" ")}"

          for i in (range_from .. range_to )
            puts "fetching msg #{i}"
            m = @mstore[i]
            break if m.nil?
            #message =  @g.msg(m.msgid)
            response_options = Array.new
            #if options.include?("UID")
            puts "append uid"
            response_options.push("UID #{i}")
            #end
            
            if request_options.include?("RFC822.SIZE")
              puts "append size"
              puts "uhmm #{m.class}"
              #response_options.push("RFC822.SIZE #{message.original.size}")
              response_options.push("RFC822.SIZE 1024")
            end
            if request_options.include?("FLAGS")
              puts "append flags"
              flags = Array.new
              flags.push("FLAGS (")
              flags.push('\Recent') if m.new?
              flags.push('\Seen') if not m.new?
              flags.push(")")
              response_options.push(flags.join(" "))
            end
            #if request_options.include?("BODY.PEEK[]")
            #  response_options.push("BODY.PEEK[]")
            #end
            send_and_log(io, "* #{i} FETCH (#{response_options.join(" ")})")
            if request_options.include?("BODY.PEEK[]")
              puts "aca mando body peek"
              message =  @g.msg(m.msgid)
              #body = message.original
              # message.conv[message.conv.length - 2].body
              send_and_log(io, "* #{i} FETCH ( BODY.PEEK[] {#{body.size}}\n#{body}\n)")
            end
          end
          puts "end fetch loop"
          send_and_log(io, "#{command_nr} OK UID FETCH completed")
        when /(.+) UID STORE (.+)/
           send_and_log(io, "#{$1} OK UID STORE completed")
        when /(.+) EXPUNGE/
           send_and_log(io, "#{$1} OK EXPUNGE completed")
        when /(.+) NOOP/
          send_and_log(io, "#{$1} OK NOOP completed")
        when /(.+) LOGOUT/
          send_and_log(io, "* BYE IMAP4rev1 Server logging out")
          send_and_log(io, "#{$1} OK LOGOUT completed")
          break
        else
          puts "Unknown command: [" + line + "]"
      end
    end
   end
 end
s = MyServer.new 1143
s.audit = true
s.start
s.join